/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.yang.usbserial.util;

import java.security.InvalidParameterException;

/**
 * Clone of Android's /core/java/com/android/internal/util/HexDump class, for use in debugging.
 * Changes: space separated hex strings
 */
public class HexDump {
    private final static char[] HEX_DIGITS = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
    };


    public static String dumpHexString(String hexString) {
        StringBuilder result = new StringBuilder();
        String[] parts = hexString.split("3B"); // 分割字符串
        for (int i = 0; i < parts.length; i++) {
            if (i == 0) {
                LogUtils.e(parts[i] + "3B  " + HexDump.hexStringToString(parts[i]) + ";");
                result.append(parts[i] + "3B  " +  HexDump.hexStringToString(parts[i]) + ";").append("\n");
            } else {
                LogUtils.e(parts[i] + "3B  " + "文件" + i + ":" + Integer.parseInt(parts[i], 16) + ";");
                result.append(parts[i] + "3B  " + "文件" + i + ":" + Integer.parseInt(parts[i], 16) + ";").append("\n");
            }
        }
        return result.toString();
    }

    /**
     * 将字节数组以十六进制的形式进行转换并打印
     *
     * @param array
     * @return
     */
    public static String dumpHexString(byte[] array) {
        return dumpHexString(array, 0, array.length);
    }

    /**
     * array 是要转换的字节数组，offset 是转换的起始位置，length 是要转换的长度。
     *
     * @param array
     * @param offset
     * @param length
     * @return
     */
    public static String dumpHexString(byte[] array, int offset, int length) {
        StringBuilder result = new StringBuilder();

        byte[] line = new byte[8];
        int lineIndex = 0;

        for (int i = offset; i < offset + length; i++) {
            if (lineIndex == line.length) {
                for (int j = 0; j < line.length; j++) {
                    if (line[j] > ' ' && line[j] < '~') {
                        result.append(new String(line, j, 1));
                    } else {
                        result.append(".");
                    }
                }

                result.append("\n");
                lineIndex = 0;
            }

            byte b = array[i];
            result.append(HEX_DIGITS[(b >>> 4) & 0x0F]);
            result.append(HEX_DIGITS[b & 0x0F]);
            result.append(" ");

            line[lineIndex++] = b;
        }

        for (int i = 0; i < (line.length - lineIndex); i++) {
            result.append("   ");
        }
        for (int i = 0; i < lineIndex; i++) {
            if (line[i] > ' ' && line[i] < '~') {
                result.append(new String(line, i, 1));
            } else {
                result.append(".");
            }
        }
        return result.toString();
    }

    public static String hexStringToString(String hexString) {
        StringBuilder output = new StringBuilder();
        for (int i = 0; i < hexString.length(); i += 2) {
            String str = hexString.substring(i, i + 2);
            output.append((char) Integer.parseInt(str, 16));
        }
        return output.toString();
    }

    public static String toHexString(byte b) {
        return toHexString(toByteArray(b));
    }

    public static String toHexString(byte[] array) {
        return toHexString(array, 0, array.length);
    }

    public static String toHexString(byte[] array, int offset, int length) {
        char[] buf = new char[length > 0 ? length * 3 - 1 : 0];

        int bufIndex = 0;
        for (int i = offset; i < offset + length; i++) {
            if (i > offset)
                buf[bufIndex++] = ' ';
            byte b = array[i];
            buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F];
            buf[bufIndex++] = HEX_DIGITS[b & 0x0F];
        }

        return new String(buf);
    }

    public static String toHexString(int i) {
        return toHexString(toByteArray(i));
    }

    public static String toHexString(short i) {
        return toHexString(toByteArray(i));
    }

    public static byte[] toByteArray(byte b) {
        byte[] array = new byte[1];
        array[0] = b;
        return array;
    }

    public static byte[] toByteArray(int i) {
        byte[] array = new byte[4];

        array[3] = (byte) (i & 0xFF);
        array[2] = (byte) ((i >> 8) & 0xFF);
        array[1] = (byte) ((i >> 16) & 0xFF);
        array[0] = (byte) ((i >> 24) & 0xFF);

        return array;
    }

    public static byte[] toByteArray(short i) {
        byte[] array = new byte[2];

        array[1] = (byte) (i & 0xFF);
        array[0] = (byte) ((i >> 8) & 0xFF);

        return array;
    }

    private static int toByte(char c) {
        if (c >= '0' && c <= '9')
            return (c - '0');
        if (c >= 'A' && c <= 'F')
            return (c - 'A' + 10);
        if (c >= 'a' && c <= 'f')
            return (c - 'a' + 10);

        throw new InvalidParameterException("Invalid hex char '" + c + "'");
    }

    /**
     * accepts any separator, e.g. space or newline
     */
//    public static byte[] hexStringToByteArray(String hexString) {
//        int length = hexString.length();
//        byte[] buffer = new byte[(length + 1) / 3];
//
//        for (int i = 0; i < length; i += 3) {
//            buffer[i / 3] = (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString.charAt(i + 1)));
//        }
//
//        return buffer;
//    }
    public static byte[] hexStringToByteArray(String hexString) {
        int len = hexString.length();
        byte[] data = new byte[len / 2];

        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
                    + Character.digit(hexString.charAt(i + 1), 16));
        }

        return data;
    }

    public static String str2HexStr(String str) {
        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder("");
        byte[] bs = str.getBytes();
        int bit;
        for (int i = 0; i < bs.length; i++) {
            bit = (bs[i] & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = bs[i] & 0x0f;
            sb.append(chars[bit]);
        }
        return sb.toString().trim();
    }


    /**
     * * 十六进制字符串装十进制
     * *
     * * @param hex
     * *            十六进制字符串
     * * @return 十进制数值
     */
    public static int hexStringToAlgorism(String hex) {
        hex = hex.toUpperCase();
        int max = hex.length();
        int result = 0;
        for (int i = max; i > 0; i--) {
            char c = hex.charAt(i - 1);
            int algorism = 0;
            if (c >= '0' && c <= '9') {
                algorism = c - '0';
            } else {
                algorism = c - 55;
            }
            result += Math.pow(16, max - i) * algorism;
        }
        return result;
    }

    public static String convertToHexAndSendData(String data) {
        StringBuilder hexData = new StringBuilder();

        // Split the input data using semicolon as a delimiter
        String[] parts = data.split(";");

        // Process the numeric parts
        for (String part : parts) {
            if (isNumeric(part)) {
                // Pad the numeric part to ensure it has 8 characters
                String paddedPart = padWithZeros(part, 8);
                // Convert the padded numeric part to hexadecimal and add it to hexData
                hexData.append(convertNumericToHex(paddedPart));
            } else {
                // If it's not a numeric part, add it as is
                hexData.append(str2HexStr(part));
            }
            // Add a semicolon as a delimiter
            hexData.append(str2HexStr(";"));
        }

        // Now, hexData contains the entire message in hexadecimal format
        // You can send this data to your USB device

        return hexData.toString();
    }

    private static boolean isNumeric(String str) {
        return str.matches("\\d+");
    }

    private static String padWithZeros(String input, int length) {
        StringBuilder result = new StringBuilder(input);
        while (result.length() < length) {
            result.insert(0, '0');
        }
        return result.toString();
    }

    private static String convertNumericToHex(String numericPart) {
        try {
            long numericValue = Long.parseLong(numericPart);
            String hexString = Long.toHexString(numericValue);
            // 补位，如果生成的16进制字符串不足8位
            while (hexString.length() < 8) {
                hexString = "0" + hexString;
            }
            return hexString;
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return "";
        }
    }
}
